package org.jeecg.modules.qyxxora.controller;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.qyxxora.entity.InterviewData;
import org.jeecg.modules.qyxxora.entity.dto.InterviewDataListDto;
import org.jeecg.modules.qyxxora.entity.dto.StatCommonDto;
import org.jeecg.modules.qyxxora.service.IInterviewDataService;
import org.jeecg.modules.qyxxora.vo.*;
import org.jeecg.modules.qyxx.enumdemo.StatisticRedisKeyConstant;
import org.jeecg.modules.qyxxora.service.IStatisticsService;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author chensherun on 2022/1/12.
 * @version 1.0
 */
@Slf4j
@Api(tags = "统计分析")
@RestController
@RequestMapping("/qyxx/statistics")
public class StatisticsController {

    @Autowired
    private IStatisticsService statisticsService;

    @Autowired
    private ISysDepartService departService;

    @Autowired
    private ISysDictService sysDictService;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 余额单位
     */
    @Value("${statistic.balance.unit:万元}")
    private String balanceUnit;

    /**
     * 余额转换除以的被除数
     */
    @Value("${statistic.balance.dividend:1}")
    private BigDecimal dividend;

    /**
     * 拼接字典项的拼接符
     */
    private final String SEPARATOR_ITEM = ",";
    /**
     * 拼接字典项的值和文本间的拼接符
     */
    private final String SEPARATOR_VALUE_TEXT = "||";

    @ApiOperation("获取金额单位")
    @PostMapping("/getBalanceUnit")
    public Result<String> getBalanceUnit() {
        return Result.OK(balanceUnit);
    }

    @ApiOperation("属期年月")
    @PostMapping("/ssnyList")
    public Result<List<String>> ssnyList() {
        String ssnyCache = redisUtil.getString(StatisticRedisKeyConstant.ssny_list + "new");
        List<String> list = null;
        if (StringUtils.isNotBlank(ssnyCache)) {
            try {
                list = JSONObject.parseObject(ssnyCache, new TypeReference<ArrayList<String>>() {{
                }});
                return Result.OK(list);
            } catch (Exception e) {
                log.error("转换缓存数据出错");
            }
        }
        list = new ArrayList<>();
        String ssny = statisticsService.selectScyszbjcMaxSsny(null);
        SimpleDateFormat ssnyFormat = new SimpleDateFormat("yyyyMM");
        Date ssnyDate;
        if (StringUtils.isBlank(ssny)) {
            ssnyDate = new Date();
        } else {
            ssnyDate = DateUtils.str2Date(ssny, ssnyFormat);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(ssnyDate);
        list.add(ssnyFormat.format(calendar.getTime()));
        for (int i = 1; i < 12; i++) {
            calendar.add(Calendar.MONTH, -1);
            list.add(ssnyFormat.format(calendar.getTime()));
        }
        redisUtil.setString(StatisticRedisKeyConstant.ssny_list, JSON.toJSONString(list), 10 * 60);
        return Result.OK(list);
    }

    @ApiOperation("地图数据")
    @PostMapping("/mapData")
    @RequiresPermissions("statistics:mapData")
    public Result<List<StatCityWarningVo>> mapData(@Validated @RequestBody StatCommonDto statCommonDto) {
        List<StatCityWarningVo> list = statisticsService.selectCityWarning(statCommonDto.getSsny());
        return Result.OK(list);
    }

    @ApiOperation("下属子机构预警响应情况")
    @PostMapping("/getChildOrgWarning")
    @RequiresPermissions("statistics:mapData")
    public Result<List<StatChildOrgWarningVo>> selectChildOrgWarning(@Validated @RequestBody StatCommonDto statCommonDto) {
        List<StatChildOrgWarningVo> statChildOrgWarningList = statisticsService.selectChildOrgWarning(statCommonDto.getSsny(), statCommonDto.getSaleNetCode());
        return Result.OK(statChildOrgWarningList);
    }

    @ApiOperation("预警概况")
    @PostMapping("/getStatWaringSituation")
    public Result<StatWaringSituation> getStatWaringSituation(@Validated @RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//        String orgCode = statCommonDto.getSaleNetCode();
        String orgCode = loginUser.getOrgCode();
        SysDepart sysDepart = departService.queryCompByOrgCode(orgCode);
        statCommonDto.setSaleNetCode(orgCode);
        StatWaringSituation statWaringSituation = statisticsService.selectStatWaringSituation(statCommonDto.getSsny(), statCommonDto.getSaleNetCode());
        if (statWaringSituation != null) {
            statWaringSituation.setSaleNetName(sysDepart.getDepartName());
        }
        return Result.OK(statWaringSituation);
    }

    @ApiOperation("预警响应概况")
    @PostMapping("/getStatWarningResponseSituation")
    public Result<StatResponseSituation> getStatWarningResponseSituation(@RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        statCommonDto.setSaleNetCode(loginUser.getOrgCode());
        StatResponseSituation statResponseSituation = statisticsService.selectStatWarningResponseSituation(statCommonDto.getSsny(), statCommonDto.getSaleNetCode());
        return Result.OK(statResponseSituation);
    }

    @ApiOperation("按指标类型统计响应率")
    @PostMapping("/getStatIndexWarningResponse")
    public Result<Map<String, List<StatIndexWarningResponseVo>>> getStatIndexWarningResponse(@RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        statCommonDto.setSaleNetCode(loginUser.getOrgCode());

        //查询数据字典（mysql）
        String itemValues = sysDictService.queryDictItemsString("zbgl_zblx", SEPARATOR_ITEM, SEPARATOR_VALUE_TEXT);

        List<StatIndexWarningResponseVo> list = statisticsService.selectStatIndexWarningResponse(statCommonDto.getSsny(), statCommonDto.getSaleNetCode(), itemValues);
        StatIndexWarningResponseVo total = new StatIndexWarningResponseVo();
        total.setIndexType("-");
        total.setIndexTypeName("客户预警汇总");
        total.setWarningCount(0);
        total.setUncheckCount(0);
        total.setCheckingCount(0);
        total.setCheckedCount(0);
        //计算响应率
        list.forEach(vo -> {
            total.setWarningCount(total.getWarningCount() + vo.getWarningCount());
            total.setUncheckCount(total.getUncheckCount() + vo.getUncheckCount());
            total.setCheckingCount(total.getCheckingCount() + vo.getCheckingCount());
            total.setCheckedCount(total.getCheckedCount() + vo.getCheckedCount());
        });
        if (total.getWarningCount() != null && total.getWarningCount() > 0) {
            total.setResponseRate(new BigDecimal((float) (total.getCheckingCount() + total.getCheckedCount()) / total.getWarningCount() * 100).setScale(2, BigDecimal.ROUND_HALF_UP));
        } else {
            total.setResponseRate(BigDecimal.ZERO);
        }
        Map<String, List<StatIndexWarningResponseVo>> map = new HashMap<>();
        map.put("total", Arrays.asList(total));
        map.put("data", list);
        return Result.OK(map);
    }


    @ApiOperation("预警情况(省)")
    @PostMapping("/provinceWarningCondition")
    @RequiresPermissions("statistics:provinceCondition")
    public Result<Map<String, List<WarningConditionVo>>> provinceWarningCondition(@RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        statCommonDto.setSaleNetCode(loginUser.getOrgCode());
        List<WarningConditionVo> list = statisticsService.selectAreaWarning(statCommonDto.getSsny());
        Map<String, List<WarningConditionVo>> map = new HashMap<>();
        WarningConditionVo conditionVo = new WarningConditionVo();
        conditionVo.initZero();
        LambdaQueryWrapper<SysDepart> wrapper = Wrappers.lambdaQuery(SysDepart.class);
        wrapper.select(SysDepart::getDepartName).eq(SysDepart::getOrgCode, loginUser.getOrgCode());
        SysDepart depart = departService.getOne(wrapper);
        conditionVo.setDepartName(depart.getDepartName());
        for (WarningConditionVo vo : list) {
            conditionVo.setTotal(conditionVo.getTotal().add(vo.getTotal()));
            conditionVo.setOrgWarningBlue(conditionVo.getOrgWarningBlue() + vo.getOrgWarningBlue());
            conditionVo.setOrgWarningOrange(conditionVo.getOrgWarningOrange() + vo.getOrgWarningOrange());
            conditionVo.setOrgWarningRed(conditionVo.getOrgWarningRed() + vo.getOrgWarningRed());
            conditionVo.setWarningBlue(conditionVo.getWarningBlue().add(vo.getWarningBlue()));
            conditionVo.setWarningOrange(conditionVo.getWarningOrange().add(vo.getWarningOrange()));
            conditionVo.setWarningRed(conditionVo.getWarningRed().add(vo.getWarningRed()));
            conditionVo.setWarningRemaining(conditionVo.getWarningRemaining().add(vo.getWarningRemaining()));

            //单位转换
            vo.setWarningRemaining(vo.getWarningRemaining().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setWarningRed(vo.getWarningRed().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setWarningOrange(vo.getWarningOrange().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setWarningBlue(vo.getWarningBlue().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setTotal(vo.getTotal().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        }
        if (conditionVo.getTotal().compareTo(BigDecimal.ZERO) != 0) {
            conditionVo.setWarningRate(conditionVo.getWarningRemaining().multiply(new BigDecimal(100)).divide(conditionVo.getTotal(), 2, BigDecimal.ROUND_HALF_UP));
        } else {
            conditionVo.setWarningRate(BigDecimal.ZERO);
        }
        //合计的单位转换
        conditionVo.setWarningBlue(conditionVo.getWarningBlue().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setWarningOrange(conditionVo.getWarningOrange().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setWarningRed(conditionVo.getWarningRed().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setWarningRemaining(conditionVo.getWarningRemaining().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setTotal(conditionVo.getTotal().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));

        map.put("data", list);
        map.put("total", Arrays.asList(conditionVo));
        return Result.OK(map);
    }

    @ApiOperation("响应情况(省)")
    @PostMapping("/provinceResponseCondition")
    @RequiresPermissions("statistics:provinceCondition")
    public Result<Map<String, List<ResponseConditionVo>>> provinceResponseCondition(@RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        statCommonDto.setSaleNetCode(loginUser.getOrgCode());
        List<ResponseConditionVo> list = statisticsService.selectAreaResponse(statCommonDto.getSsny());
        ResponseConditionVo conditionVo = new ResponseConditionVo();
        conditionVo.initZero();
        LambdaQueryWrapper<SysDepart> wrapper = Wrappers.lambdaQuery(SysDepart.class);
        wrapper.select(SysDepart::getDepartName).eq(SysDepart::getOrgCode, loginUser.getOrgCode());
        SysDepart depart = departService.getOne(wrapper);
        conditionVo.setDepartName(depart.getDepartName());
        Map<String, List<ResponseConditionVo>> map = new HashMap<>();
        for (ResponseConditionVo vo : list) {
            conditionVo.setBeVerified(conditionVo.getBeVerified() + vo.getBeVerified());
            conditionVo.setIsVerifie(conditionVo.getIsVerifie() + vo.getIsVerifie());
            conditionVo.setVerifieding(conditionVo.getVerifieding() + vo.getVerifieding());
            conditionVo.setTotal(conditionVo.getTotal() + vo.getTotal());
        }
        if (conditionVo.getTotal() != 0) {
            conditionVo.setResponsivity(new BigDecimal((conditionVo.getIsVerifie() + conditionVo.getVerifieding())).multiply(new BigDecimal(100)).divide(new BigDecimal(conditionVo.getTotal()), 2, BigDecimal.ROUND_HALF_UP));
        } else {
            conditionVo.setResponsivity(BigDecimal.ZERO);
        }
        map.put("data", list);
        map.put("total", Arrays.asList(conditionVo));
        return Result.OK(map);
    }

    @ApiOperation("预警情况(区域)")
    @PostMapping("/districtWarningCondition")
    @RequiresPermissions("statistics:districtCondition")
    public Result<Map<String, List<WarningConditionVo>>> districtWarningCondition(@RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        statCommonDto.setSaleNetCode(loginUser.getOrgCode());
        List<String> ids = statisticsService.selectIdByCode(statCommonDto.getSaleNetCode());
        List<WarningConditionVo> list = statisticsService.selectDistrictWarning(ids, statCommonDto.getSsny());
        Map<String, List<WarningConditionVo>> map = new HashMap<>();
        WarningConditionVo conditionVo = new WarningConditionVo();
        conditionVo.initZero();
        LambdaQueryWrapper<SysDepart> wrapper = Wrappers.lambdaQuery(SysDepart.class);
        wrapper.select(SysDepart::getDepartName).eq(SysDepart::getOrgCode, loginUser.getOrgCode());
        SysDepart depart = departService.getOne(wrapper);
        conditionVo.setDepartName(depart.getDepartName());
        for (WarningConditionVo vo : list) {
            conditionVo.setTotal(conditionVo.getTotal().add(vo.getTotal()));
            conditionVo.setOrgWarningBlue(conditionVo.getOrgWarningBlue() + vo.getOrgWarningBlue());
            conditionVo.setOrgWarningOrange(conditionVo.getOrgWarningOrange() + vo.getOrgWarningOrange());
            conditionVo.setOrgWarningRed(conditionVo.getOrgWarningRed() + vo.getOrgWarningRed());
            conditionVo.setWarningBlue(conditionVo.getWarningBlue().add(vo.getWarningBlue()));
            conditionVo.setWarningOrange(conditionVo.getWarningOrange().add(vo.getWarningOrange()));
            conditionVo.setWarningRed(conditionVo.getWarningRed().add(vo.getWarningRed()));
            conditionVo.setWarningRemaining(conditionVo.getWarningRemaining().add(vo.getWarningRemaining()));

            //单位转换
            vo.setWarningRemaining(vo.getWarningRemaining().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setWarningRed(vo.getWarningRed().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setWarningOrange(vo.getWarningOrange().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setWarningBlue(vo.getWarningBlue().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setTotal(vo.getTotal().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        }
        if (conditionVo.getTotal().compareTo(BigDecimal.ZERO) != 0) {
            conditionVo.setWarningRate(conditionVo.getWarningRemaining().multiply(new BigDecimal(100)).divide(conditionVo.getTotal(), 2, BigDecimal.ROUND_HALF_UP));
        } else {
            conditionVo.setWarningRate(BigDecimal.ZERO);
        }

        //合计的单位转换
        conditionVo.setWarningBlue(conditionVo.getWarningBlue().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setWarningOrange(conditionVo.getWarningOrange().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setWarningRed(conditionVo.getWarningRed().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setWarningRemaining(conditionVo.getWarningRemaining().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setTotal(conditionVo.getTotal().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));

        map.put("data", list);
        map.put("total", Arrays.asList(conditionVo));
        return Result.OK(map);
    }

    @ApiOperation("响应情况(区域)")
    @PostMapping("/districtResponseCondition")
    @RequiresPermissions("statistics:districtCondition")
    public Result<Map<String, List<ResponseConditionVo>>> districtResponseCondition(@RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        statCommonDto.setSaleNetCode(loginUser.getOrgCode());
        List<String> ids = statisticsService.selectIdByCode(statCommonDto.getSaleNetCode());
        List<ResponseConditionVo> list = statisticsService.selectDistrictResponse(ids, statCommonDto.getSsny());
        ResponseConditionVo conditionVo = new ResponseConditionVo();
        conditionVo.initZero();
        LambdaQueryWrapper<SysDepart> wrapper = Wrappers.lambdaQuery(SysDepart.class);
        wrapper.select(SysDepart::getDepartName).eq(SysDepart::getOrgCode, loginUser.getOrgCode());
        SysDepart depart = departService.getOne(wrapper);
        conditionVo.setDepartName(depart.getDepartName());
        Map<String, List<ResponseConditionVo>> map = new HashMap<>();
        for (ResponseConditionVo vo : list) {
            conditionVo.setBeVerified(conditionVo.getBeVerified() + vo.getBeVerified());
            conditionVo.setIsVerifie(conditionVo.getIsVerifie() + vo.getIsVerifie());
            conditionVo.setVerifieding(conditionVo.getVerifieding() + vo.getVerifieding());
            conditionVo.setTotal(conditionVo.getTotal() + vo.getTotal());
        }
        if (conditionVo.getTotal() != 0) {
            conditionVo.setResponsivity(new BigDecimal((conditionVo.getIsVerifie() + conditionVo.getVerifieding())).multiply(new BigDecimal(100)).divide(new BigDecimal(conditionVo.getTotal()), 2, BigDecimal.ROUND_HALF_UP));
        } else {
            conditionVo.setResponsivity(BigDecimal.ZERO);
        }
        map.put("data", list);
        map.put("total", Arrays.asList(conditionVo));
        return Result.OK(map);
    }

    @ApiOperation("预警情况（按企业类型）")
    @PostMapping("/getWarningByOrgType")
    public Result<Map<String, List<StatWarningByOrgTypeVo>>> getWarningByOrgType(@Validated @RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        statCommonDto.setSaleNetCode(loginUser.getOrgCode());

        //查询数据字典（mysql）
        String itemValues = sysDictService.queryDictItemsString("customer_org_type", SEPARATOR_ITEM, SEPARATOR_VALUE_TEXT);

        List<StatWarningByOrgTypeVo> dataList = statisticsService.selectWarningByOrgType(statCommonDto.getSsny(), statCommonDto.getSaleNetCode(), itemValues);
        StatWarningByOrgTypeVo total = new StatWarningByOrgTypeVo();
        total.initZero();
        total.setOrgTypeCode("-");
        total.setOrgTypeName("所有企业");
        dataList.forEach(vo -> {
            vo.setWarningBalance(vo.getBalanceL1().add(vo.getBalanceL2()).add(vo.getBalanceL3()));
            if (vo.getBalance() != null && vo.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                vo.setWaringRate(vo.getWarningBalance().multiply(new BigDecimal(100)).divide(vo.getBalance(), 2, BigDecimal.ROUND_HALF_UP));
            } else {
                vo.setWaringRate(BigDecimal.ZERO);
            }
            total.setAuthCusCount(total.getAuthCusCount() + vo.getAuthCusCount());
            total.setWarningCusCount(total.getWarningCusCount() + vo.getWarningCusCount());
            total.setBalance(total.getBalance().add(vo.getBalance()));
            total.setBalanceL1(total.getBalanceL1().add(vo.getBalanceL1()));
            total.setBalanceL2(total.getBalanceL2().add(vo.getBalanceL2()));
            total.setBalanceL3(total.getBalanceL3().add(vo.getBalanceL3()));

            //单位转换
            vo.setBalance(vo.getBalance().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setWarningBalance(vo.getWarningBalance().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setBalanceL1(vo.getBalanceL1().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setBalanceL2(vo.getBalanceL2().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setBalanceL3(vo.getBalanceL3().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        });
        total.setWarningBalance(total.getBalanceL1().add(total.getBalanceL2()).add(total.getBalanceL3()));
        if (total.getBalance() != null && total.getBalance().compareTo(BigDecimal.ZERO) > 0) {
            total.setWaringRate(total.getWarningBalance().multiply(new BigDecimal(100)).divide(total.getBalance(), 2, BigDecimal.ROUND_HALF_UP));
        }

        //单位转换
        total.setBalance(total.getBalance().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        total.setWarningBalance(total.getWarningBalance().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        total.setBalanceL1(total.getBalanceL1().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        total.setBalanceL2(total.getBalanceL2().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        total.setBalanceL3(total.getBalanceL3().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));

        Map<String, List<StatWarningByOrgTypeVo>> map = new HashMap<>();
        map.put("data", dataList);
        map.put("total", Arrays.asList(total));
        return Result.OK(map);
    }

    @ApiOperation("响应情况（按企业类型）")
    @PostMapping("/getResponseByOrgType")
    public Result<Map<String, List<StatResponseByOrgTypeVo>>> selectResponseByOrgType(@Validated @RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        statCommonDto.setSaleNetCode(loginUser.getOrgCode());

        //查询数据字典（mysql）
        String itemValues = sysDictService.queryDictItemsString("customer_org_type", SEPARATOR_ITEM, SEPARATOR_VALUE_TEXT);
        List<StatResponseByOrgTypeVo> dataList = statisticsService.selectResponseByOrgType(statCommonDto.getSsny(), statCommonDto.getSaleNetCode(), itemValues);
        StatResponseByOrgTypeVo total = new StatResponseByOrgTypeVo();
        total.initZero();
        total.setOrgTypeCode("-");
        total.setOrgTypeName("所有企业");
        dataList.forEach(vo -> {
            if (vo.getWarningCount() != null && vo.getWarningCount() > 0) {
                //System.out.println("responseRate:" + (float)(vo.getCheckingCount() + vo.getCheckedCount()) / vo.getWarningCount() * 100);
                vo.setResponseRate(new BigDecimal((float) (vo.getCheckingCount() + vo.getCheckedCount()) / vo.getWarningCount() * 100).setScale(2, BigDecimal.ROUND_HALF_UP));
            } else {
                vo.setResponseRate(BigDecimal.ZERO);
            }
            total.setWarningCount(total.getWarningCount() + vo.getWarningCount());
            total.setUncheckCount(total.getUncheckCount() + vo.getUncheckCount());
            total.setCheckingCount(total.getCheckingCount() + vo.getCheckingCount());
            total.setCheckedCount(total.getCheckedCount() + vo.getCheckedCount());
        });
        if (total.getWarningCount() > 0) {
            total.setResponseRate(new BigDecimal((float) (total.getCheckingCount() + total.getCheckedCount()) / total.getWarningCount() * 100).setScale(2, BigDecimal.ROUND_HALF_UP));
        } else {
            total.setResponseRate(BigDecimal.ZERO);
        }
        Map<String, List<StatResponseByOrgTypeVo>> map = new HashMap<>();
        map.put("data", dataList);
        map.put("total", Arrays.asList(total));
        return Result.OK(map);
    }

    @ApiOperation("预警情况（按行业类型）")
    @PostMapping("/getWarningByIndustryType")
    public Result<Map<String, List<WarningByIndustryTypeVo>>> getWarningByIndustryType(@RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        statCommonDto.setSaleNetCode(loginUser.getOrgCode());
        //查询数据字典（mysql）
        String itemValues = sysDictService.queryDictItemsString("industry_type", SEPARATOR_ITEM, SEPARATOR_VALUE_TEXT);
        statCommonDto.setDictItems(itemValues);
        List<WarningByIndustryTypeVo> list = statisticsService.getWarningByIndustryType(statCommonDto);
        Map<String, List<WarningByIndustryTypeVo>> map = new HashMap<>();
        WarningByIndustryTypeVo conditionVo = new WarningByIndustryTypeVo();
        conditionVo.initZero();
        conditionVo.setIndustryName("行业总汇");
        for (WarningByIndustryTypeVo vo : list) {
            conditionVo.setTotal(conditionVo.getTotal().add(vo.getTotal()));
            conditionVo.setOrgWarningBlue(conditionVo.getOrgWarningBlue() + vo.getOrgWarningBlue());
            conditionVo.setOrgWarningOrange(conditionVo.getOrgWarningOrange() + vo.getOrgWarningOrange());
            conditionVo.setOrgWarningRed(conditionVo.getOrgWarningRed() + vo.getOrgWarningRed());
            conditionVo.setWarningBlue(conditionVo.getWarningBlue().add(vo.getWarningBlue()));
            conditionVo.setWarningOrange(conditionVo.getWarningOrange().add(vo.getWarningOrange()));
            conditionVo.setWarningRed(conditionVo.getWarningRed().add(vo.getWarningRed()));
            conditionVo.setWarningRemaining(conditionVo.getWarningRemaining().add(vo.getWarningRemaining()));

            //单位转换
            vo.setWarningRemaining(vo.getWarningRemaining().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setWarningRed(vo.getWarningRed().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setWarningOrange(vo.getWarningOrange().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setWarningBlue(vo.getWarningBlue().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
            vo.setTotal(vo.getTotal().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        }
        if (conditionVo.getTotal().compareTo(BigDecimal.ZERO) != 0) {
            conditionVo.setWarningRate(conditionVo.getWarningRemaining().multiply(new BigDecimal(100)).divide(conditionVo.getTotal(), 2, BigDecimal.ROUND_HALF_UP));
        } else {
            conditionVo.setWarningRate(BigDecimal.ZERO);
        }

        //单位转换
        conditionVo.setWarningRemaining(conditionVo.getWarningRemaining().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setWarningRed(conditionVo.getWarningRed().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setWarningOrange(conditionVo.getWarningOrange().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setWarningBlue(conditionVo.getWarningBlue().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));
        conditionVo.setTotal(conditionVo.getTotal().divide(dividend, 2, BigDecimal.ROUND_HALF_UP));

        map.put("data", list);
        map.put("total", Arrays.asList(conditionVo));
        return Result.OK(map);
    }

    @ApiOperation("响应情况（按行业类型）")
    @PostMapping("/getResponseByIndustryType")
    public Result<Map<String, List<ResponseByIndustryTypeVo>>> getResponseByIndustryType(@RequestBody StatCommonDto statCommonDto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        statCommonDto.setSaleNetCode(loginUser.getOrgCode());
        //查询数据字典（mysql）
        String itemValues = sysDictService.queryDictItemsString("industry_type", SEPARATOR_ITEM, SEPARATOR_VALUE_TEXT);
        statCommonDto.setDictItems(itemValues);
        List<ResponseByIndustryTypeVo> list = statisticsService.getResponseByIndustryType(statCommonDto);
        ResponseByIndustryTypeVo conditionVo = new ResponseByIndustryTypeVo();
        conditionVo.initZero();
        conditionVo.setIndustryName("行业总汇");
        Map<String, List<ResponseByIndustryTypeVo>> map = new HashMap<>();
        for (ResponseByIndustryTypeVo vo : list) {
            conditionVo.setBeVerified(conditionVo.getBeVerified() + vo.getBeVerified());
            conditionVo.setIsVerifie(conditionVo.getIsVerifie() + vo.getIsVerifie());
            conditionVo.setVerifieding(conditionVo.getVerifieding() + vo.getVerifieding());
            conditionVo.setTotal(conditionVo.getTotal() + vo.getTotal());
        }
        if (conditionVo.getTotal() != 0) {
            conditionVo.setResponsivity(new BigDecimal((conditionVo.getIsVerifie() + conditionVo.getVerifieding())).multiply(new BigDecimal(100)).divide(new BigDecimal(conditionVo.getTotal()), 2, BigDecimal.ROUND_HALF_UP));
        } else {
            conditionVo.setResponsivity(BigDecimal.ZERO);
        }
        map.put("data", list);
        map.put("total", Arrays.asList(conditionVo));
        return Result.OK(map);
    }

    @ApiOperation("预警趋势变化")
    @PostMapping("/getWarningTrendChart")
    public Result<List<StatWarningTrendChartVo>> getWarningTrendChart() {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String saleNetCode = loginUser.getOrgCode();
        String ssny = statisticsService.selectScyszbjcMaxSsny(null);
        SimpleDateFormat ssnyFormat = new SimpleDateFormat("yyyyMM");
        Date ssnyDate;
        if (StringUtils.isBlank(ssny)) {
            ssnyDate = new Date();
        } else {
            ssnyDate = DateUtils.str2Date(ssny, ssnyFormat);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(ssnyDate);
        calendar.add(Calendar.MONTH, -11);
        String ssnyq = ssnyFormat.format(calendar.getTime());
        List<StatWarningTrendChartVo> statWarningTrendChartVos = statisticsService.selectWarningTrendChart(ssnyq, ssny, saleNetCode);
        return Result.OK(statWarningTrendChartVos);
    }

    @ApiOperation("响应趋势变化")
    @PostMapping("/getResponeTrendChart")
    public Result<List<StatResponseTrendChartVo>> getResponeTrendChart() {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String saleNetCode = loginUser.getOrgCode();
        String ssny = statisticsService.selectScyszbjcMaxSsny(null);
        SimpleDateFormat ssnyFormat = new SimpleDateFormat("yyyyMM");
        Date ssnyDate;
        if (StringUtils.isBlank(ssny)) {
            ssnyDate = new Date();
        } else {
            ssnyDate = DateUtils.str2Date(ssny, ssnyFormat);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(ssnyDate);
        calendar.add(Calendar.MONTH, -11);
        String ssnyq = ssnyFormat.format(calendar.getTime());
        List<StatResponseTrendChartVo> statResponseTrendChartVos = statisticsService.selectResponseTrendChart(ssnyq, ssny, saleNetCode);
        return Result.OK(statResponseTrendChartVos);
    }

    @ApiOperation("上传走访数据")
    @PostMapping("/uploadInterviewData")
    public Result uploadInterviewData(MultipartFile file, String ssny) {
        if (StringUtil.isBlank(ssny)) {
            ssny = DateUtil.format(org.jeecg.modules.qyxx.util.DateUtils.getInstance().getLastMonth(), "yyyyMM");
        }
        boolean flag = statisticsService.analysisInterviewDataExcle(file, ssny);
        if (flag) {
            return Result.ok();
        } else {
            return Result.error("上传Excel解析异常");
        }
    }

    @Value("${interviewExcelModelPath:}")
    private String path;

    @ApiOperation("下载Excel模板")
    @GetMapping("/download")
    public HttpServletResponse download(HttpServletResponse response) {
        try {
            // path是指欲下载的文件的路径。
            File file = new File(path);
            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(path));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return response;
    }

    @Autowired
    private IInterviewDataService interviewDataService;

    @ApiOperation("走访数据列表")
    @PostMapping("/interviewDataList")
    public Result<List<InterviewDataVo>> interviewDataList(@RequestBody InterviewDataListDto dataListDto) {
        String ssny = dataListDto.getSsny();
        if (StringUtil.isBlank(ssny)) {
            ssny = DateUtil.format(org.jeecg.modules.qyxx.util.DateUtils.getInstance().getLastMonth(), "yyyyMM");
            dataListDto.setSsny(ssny);
        }
        LambdaQueryWrapper<InterviewData> wrapper = Wrappers.lambdaQuery(InterviewData.class);
        wrapper.select(InterviewData::getAreaName).eq(InterviewData::getSsny, dataListDto.getSsny()).eq(InterviewData::getStatus, dataListDto.getStatus()).groupBy(InterviewData::getAreaName);
        List<String> areaList = interviewDataService.listObjs(wrapper, a -> {
            return new String(a.toString());
        });
        if (areaList == null){
            Result<List<InterviewDataVo>> result = new Result<>();
            return result.error500("该月暂无数据");
        }
        List<InterviewDataVo> list = new ArrayList<>();
        for (String area : areaList) {
            InterviewDataVo vo = new InterviewDataVo();
            List<InterviewDataDetailVo> interviewData = interviewDataService.interviewDataList(dataListDto, area);

            InterviewDataDetailVo dataDetailVo = new InterviewDataDetailVo();
            BigDecimal riskCount = BigDecimal.ZERO; //小计项目总数
            BigDecimal interviewCount = BigDecimal.ZERO; // 小计走访数
            BigDecimal countRate = BigDecimal.ZERO; // 小计比例
            for (InterviewDataDetailVo detailVo : interviewData) {
                BigDecimal riskUserNum = detailVo.getRiskUserNum();
                BigDecimal interviewUserNum = detailVo.getInterviewUserNum();
                riskCount = riskCount.add(riskUserNum);
                interviewCount = interviewCount.add(interviewUserNum);
            }
            if (riskCount.compareTo(BigDecimal.ZERO) != 0) {
                countRate = interviewCount.divide(riskCount, 2, BigDecimal.ROUND_HALF_UP);
            }
            dataDetailVo.setAreaName(area);
            dataDetailVo.setName("小计");
            dataDetailVo.setRiskUserNum(riskCount);
            dataDetailVo.setInterviewUserNum(interviewCount);
            dataDetailVo.setValue(countRate);
            interviewData.add(dataDetailVo);

            vo.setAreaName(area);
            vo.setDetails(interviewData);
            list.add(vo);
        }
        return Result.OK(list);
    }

    @ApiOperation("走访数据地图")
    @PostMapping("/interviewDataMap")
    public Result<InterviewMapCountVo> interviewDataMap(@RequestBody InterviewDataListDto dataListDto) throws ParseException {
        String ssny = dataListDto.getSsny();
        if (StringUtil.isBlank(ssny)) {
            ssny = DateUtil.format(org.jeecg.modules.qyxx.util.DateUtils.getInstance().getLastMonth(), "yyyyMM");
            dataListDto.setSsny(ssny);
        }
        InterviewMapCountVo mapCountVo = interviewDataService.mapCount(dataListDto);
        if (mapCountVo == null){
            Result<InterviewMapCountVo> result = new Result<>();
            return result.error500("该月暂无数据");
        }
        BigDecimal interviewCount = mapCountVo.getInterviewCount();
        BigDecimal riskCount = mapCountVo.getRiskCount();
        if (riskCount == null || interviewCount == null || riskCount.compareTo(BigDecimal.ZERO) == 0 || interviewCount.compareTo(BigDecimal.ZERO) == 0) {
            mapCountVo.setInterviewRate(BigDecimal.ZERO);
        } else {
            BigDecimal rate = interviewCount.divide(riskCount, 4, BigDecimal.ROUND_HALF_UP);
            mapCountVo.setInterviewRate(rate);
        }
        BigDecimal interviewRate = mapCountVo.getInterviewRate();


        List<InterviewDataDetailVo> list = interviewDataService.interviewMapList(dataListDto);
        mapCountVo.setDetails(list);

        ssny = dataListDto.getSsny();
        Date dateTime = DateUtil.parse(ssny, "yyyyMM");
        Date month = org.jeecg.modules.qyxx.util.DateUtils.getInstance().getLastMonth(DateUtil.format(dateTime, "yyyy-MM-dd"));
        dataListDto.setSsny(DateUtil.format(month, "yyyyMM"));
        InterviewMapCountVo oldVo = interviewDataService.mapCount(dataListDto);
        if (oldVo != null) {
            BigDecimal oldRiskCount = oldVo.getRiskCount();
            BigDecimal oldInterviewCount = oldVo.getInterviewCount();
            if (oldRiskCount == null || oldInterviewCount == null || oldRiskCount.compareTo(BigDecimal.ZERO) == 0 || oldInterviewCount.compareTo(BigDecimal.ZERO) == 0) {
                oldVo.setInterviewRate(BigDecimal.ZERO);
            } else {
                BigDecimal rate = oldInterviewCount.divide(oldRiskCount, 4, BigDecimal.ROUND_HALF_UP);
                oldVo.setInterviewRate(rate);
            }
            BigDecimal oldInterviewRate = oldVo.getInterviewRate();

            BigDecimal riskCountRate;
            if (riskCount == null || oldRiskCount == null) {
                riskCountRate = null;
            } else if (oldRiskCount.compareTo(BigDecimal.ZERO) == 0) {
                riskCountRate = BigDecimal.ONE;
            } else {
                riskCountRate = riskCount.subtract(oldRiskCount).divide(oldRiskCount, 4, BigDecimal.ROUND_HALF_UP);
            }

            BigDecimal interviewCountRate;
            if (interviewCount == null || oldInterviewCount == null) {
                interviewCountRate = null;
            } else if (oldInterviewCount.compareTo(BigDecimal.ZERO) == 0) {
                interviewCountRate = BigDecimal.ONE;
            } else {
                interviewCountRate = interviewCount.subtract(oldInterviewCount).divide(oldInterviewCount, 4, BigDecimal.ROUND_HALF_UP);
            }

            BigDecimal interviewCountGrowthRate;
            if (interviewRate == null || oldInterviewRate == null) {
                interviewCountGrowthRate = null;
            } else if (oldInterviewRate.compareTo(BigDecimal.ZERO) == 0) {
                interviewCountGrowthRate = BigDecimal.ONE;
            } else {
                interviewCountGrowthRate = interviewRate.subtract(oldInterviewRate).divide(oldInterviewRate, 4, BigDecimal.ROUND_HALF_UP);
            }

            mapCountVo.setRiskCountRate(riskCountRate);
            mapCountVo.setInterviewCountRate(interviewCountRate);
            mapCountVo.setInterviewCountGrowthRate(interviewCountGrowthRate);
        }
        return Result.OK(mapCountVo);
    }
}
